<style lang="scss" scoped>
.chat-message {
    color: #333;

    .message,
    .current-response {

        white-space: pre-wrap;
        margin-bottom: 20px;
    }

    .current-response {
        background-color: aqua;
    }

    :deep(.code-block-header) {
        display: flex;
        justify-content: space-between;
        align-items: center;
    }

    :deep(.code-block-body) {
        border-radius: 4px;
    }

    .info {
        display: flex;
    }

    .user-text {
        background-color: #D2F9D1;
    }

    .ai-text {
        background-color: #F5F6F8;
    }

    .message-reply {
        margin-top: 12px;
        padding: 20px;
        border-radius: 8px;
    }
}
</style>

<template>
    <div class="chat-message">
        <div v-if="chatMessage.content" class="message markdown-body">
            <div class="info" :style="{ justifyContent: chatMessage.role === 'user' ? 'flex-end' : 'flex-start' }">
                <Avatar :info="{ id: 1, name: chatMessage.role, avatar: '' }" :time="chatMessage.created_at"
                    :alignx="chatMessage.role === 'user' ? 'right' : 'left'" />
            </div>
            <div v-html="text" class="message-reply" :class="chatMessage.role + '-text'"></div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, computed, nextTick, watch } from 'vue'
import MarkdownIt from 'markdown-it'
import MdKatex from '@vscode/markdown-it-katex'
import MdLinkAttributes from 'markdown-it-link-attributes'
import MdMermaid from 'mermaid-it-markdown'
import hljs from 'highlight.js'
import { useBasicLayout } from '@/hooks/useBasicLayout'
import { useScroll } from '@/hooks/useScroll'
import { t } from '@/locales'
import type { ChatMessage } from '@/type/index'
import Avatar from '@/components/chat/avatar.vue'

interface Props {
    chatMessage: ChatMessage
}


const { isMobile } = useBasicLayout()
const props = defineProps<Props>()

const { scrollRef, scrollToBottom, scrollToBottomIfAtBottom } = useScroll()

const mdi = new MarkdownIt({
    html: false,
    linkify: true,
    highlight(code, language) {
        const validLang = !!(language && hljs.getLanguage(language))
        if (validLang) {
            const lang = language ?? ''
            return highlightBlock(hljs.highlight(code, { language: lang }).value, lang)
        }
        return highlightBlock(hljs.highlightAuto(code).value, '')
    },
})

mdi.use(MdLinkAttributes, { attrs: { target: '_blank', rel: 'noopener' } }).use(MdKatex).use(MdMermaid)

const escapeBrackets = (text: string) => {
    const pattern = /(```[\s\S]*?```|`.*?`)|\\\[([\s\S]*?[^\\])\\\]|\\\((.*?)\\\)/g
    return text.replace(pattern, (match, codeBlock, squareBracket, roundBracket) => {
        if (codeBlock)
            return codeBlock
        else if (squareBracket)
            return `$$${squareBracket}$$`
        else if (roundBracket)
            return `$${roundBracket}$`
        return match
    })
}
const text = computed(() => {
    const value = props.chatMessage.content ?? ''
    // if (!props.asRawText) {
    // 对数学公式进行处理，自动添加 $$ 符号
    const escapedText = escapeBrackets(escapeDollarNumber(value))
    return mdi.render(escapedText)
    // }
    // return value
})

const currentResponse = computed(() => {
    const value = props.currentResponse ?? ''
    // if (!props.asRawText) {
    // 对数学公式进行处理，自动添加 $$ 符号
    const escapedText = escapeBrackets(escapeDollarNumber(value))
    return mdi.render(escapedText)
    // }
    // return value
})

function escapeDollarNumber(text: string) {
    let escapedText = ''

    for (let i = 0; i < text.length; i += 1) {
        let char = text[i]
        const nextChar = text[i + 1] || ' '

        if (char === '$' && nextChar >= '0' && nextChar <= '9')
            char = '\\$'

        escapedText += char
    }

    return escapedText
}

function highlightBlock(str: string, lang?: string) {
    return `<pre class="code-block-wrapper"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span><span class="code-block-header__copy">${t('chat.copyCode')}</span></div><code class="hljs code-block-body ${lang}">${str}</code></pre>`
}

</script>
